package com.nanyang.tms.manager.cost.handler;

import com.nanyang.common.core.flow.context.TransHandlerContext;
import com.nanyang.common.core.flow.handler.AbstractTransHandler;
import com.nanyang.tms.common.dict.TmsExceptionEnum;
import com.nanyang.tms.common.exception.TmsManagerException;
import com.nanyang.tms.common.util.TmsExceptionUtil;
import com.nanyang.tms.dao.cost.CostPartCityDao;
import com.nanyang.tms.dao.cost.CostPartCountyDao;
import com.nanyang.tms.dao.cost.CostPartZipcodeDao;
import com.nanyang.tms.dao.cost.CostWeightRecordDao;
import com.nanyang.tms.domain.cost.CostPricePartCountyVO;
import com.nanyang.tms.domain.cost.CostPriceWeightRecordVO;
import com.nanyang.tms.domain.cost.context.CalculateCostFreightContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class CalculateCostFreightHandler extends AbstractTransHandler {
	@Autowired
	private CostPartCountyDao costPartCountyDao;
	@Autowired
	private CostPartCityDao costPartCityDao;
	@Autowired
	private CostPartZipcodeDao costPartZipcodeDao;
	@Autowired
	private CostWeightRecordDao costWeightRecordDao;
	

	@Override
	public boolean isAsync() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean handle(TransHandlerContext context) {
		CalculateCostFreightContext calculateFreightContext = (CalculateCostFreightContext) context
				.getInnerContext(CalculateCostFreightContext.class);
		
		
		try {
			// 根据产品编码和国家码 获取分区信息 一个分区中 相同的国家只有一个
			CostPricePartCountyVO costPricePartCountry = costPartCountyDao.getCostPricePartCountry(
					calculateFreightContext.getProductCode(), calculateFreightContext.getCountyCode());
			if (costPricePartCountry == null) {
				throw new TmsManagerException(TmsExceptionEnum.PART_RULE_IS_NOT_EXIST.getCode(),
						TmsExceptionEnum.PART_RULE_IS_NOT_EXIST.getMessage());
			}
			// 分区中是城市方案的话 查询国家是否有对应的城市 没有的话 抛出异常
			if (costPricePartCountry.getSchemeTypeCode().equals("city_scheme")) {
				Integer count = costPartCityDao.countParctCity(costPricePartCountry.getPartCountyCode(),
						calculateFreightContext.getCityCode());
				if (count == 0) {
					throw new TmsManagerException(TmsExceptionEnum.PART_RULE_IS_NOT_EXIST.getCode(),
							TmsExceptionEnum.PART_RULE_IS_NOT_EXIST.getMessage());
				}
				// 分区中是邮编方案的话 查询国家是否有对应的邮编  没有的话 抛出异常
			} else if (costPricePartCountry.getSchemeTypeCode().equals("zipcode_scheme")) {
				Integer count = costPartZipcodeDao.countPartZipcode(costPricePartCountry.getPartCountyCode(),
						calculateFreightContext.getCityCode());
				if (count == 0) {
					throw new TmsManagerException(TmsExceptionEnum.PART_RULE_IS_NOT_EXIST.getCode(),
							TmsExceptionEnum.PART_RULE_IS_NOT_EXIST.getMessage());
				}
			} else {
				List<CostPriceWeightRecordVO> weightRecords = costWeightRecordDao
						.getWeightRecord(costPricePartCountry.getCostCode(), costPricePartCountry.getPartCode());
				validateWeightRecords(weightRecords);
				AtomicInteger index = new AtomicInteger(-1);
				CostPriceWeightRecordVO matchWeightRecord = weightRecords.stream().filter(x -> {
					index.getAndIncrement();
					if (calculateFreightContext.getTotalChargeWeight().compareTo(x.getWeightStart()) == 1
							&& (calculateFreightContext.getTotalChargeWeight().compareTo(x.getWeightEnd()) == 0
									|| calculateFreightContext.getTotalChargeWeight().compareTo(x.getWeightEnd()) == -1)) {
						return true;
					} else {
						return false;
					}
				}).findFirst().get();
				//计算运费
				BigDecimal amount = calFreight(matchWeightRecord, index.get(), calculateFreightContext.getTotalChargeWeight(), weightRecords);
				calculateFreightContext.setAmount(amount);
			}
			return true;
		} catch (Exception e) {
			throw TmsExceptionUtil.wrapException(e);
		}
		
	}

	@SuppressWarnings("unused")
	private void validateWeightRecords(List<CostPriceWeightRecordVO> weightRecords) {
		for (int i = 0; i < weightRecords.size(); i++) {
			if (i == 0) {
				if (weightRecords.get(i).getChargingCode().equals("xdj")
						|| weightRecords.get(i).getChargingCode().equals("xjdj")) {
					throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
							TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
				}
			} else if (i > 0 && i < weightRecords.size() - 1) {
				if (weightRecords.get(i).equals("xdj")) {
					// 单价、续阶单价、续单价
					if (weightRecords.get(i - 1).equals("dj") || weightRecords.get(i - 1).equals("xdj")
							|| weightRecords.get(i - 1).equals("xjdj")) {
						throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
								TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
					}
					if (weightRecords.get(i + 1).equals("xdj") || weightRecords.get(i + 1).equals("xjdj")) {
						throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
								TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
					}
				}
				if (weightRecords.get(i).equals("xjdj")) {
					// 单价、续阶单价、续单价
					if (weightRecords.get(i - 1).equals("dj") || weightRecords.get(i - 1).equals("xdj")) {
						throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
								TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
					}
					if (weightRecords.get(i + 1).equals("xdj")) {
						throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
								TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
					}
				}
			} else {
				if (weightRecords.get(i).equals("xdj")) {
					// 单价、续阶单价、续单价
					if (weightRecords.get(i - 1).equals("dj") || weightRecords.get(i - 1).equals("xdj")
							|| weightRecords.get(i - 1).equals("xjdj")) {
						throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
								TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
					}
				}
				if (weightRecords.get(i).equals("xjdj")) {
					// 单价、续阶单价、续单价
					if (weightRecords.get(i - 1).equals("dj") || weightRecords.get(i - 1).equals("xdj")) {
						throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
								TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
					}
				}
			}

		}
	}

	@SuppressWarnings("unused")
	private BigDecimal calFreight(CostPriceWeightRecordVO weightRecord, Integer index, BigDecimal totalChargeWeight,
			List<CostPriceWeightRecordVO> weightRecords) {
		if (weightRecord.getChargingCode().equals("dj")) {
			return weightRecord.getPrice().multiply(totalChargeWeight.divide(weightRecord.getWeightCharging(),2,BigDecimal.ROUND_HALF_UP));
		} else if (weightRecord.getChargingCode().equals("zj")) {
			return weightRecord.getPrice();
		} else if (weightRecord.getChargingCode().equals("xdj")) {
			// 续单价费用计算公式 ：首重+(计费重-weightstart)*续单价
			if(weightRecords.get(index - 1).getChargingCode().equals("zj")){
				return weightRecords.get(index - 1).getPrice().add(weightRecord.getPrice().multiply(totalChargeWeight.subtract(weightRecord.getWeightStart()).divide(weightRecord.getWeightCharging(),2,BigDecimal.ROUND_HALF_UP)));
			}else{
				throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
						TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
			}
		} else if (weightRecord.getChargingCode().equals("xjdj")) {
			// 续阶单价费用计算公式 ：首重+(计费重-weightstart)*续阶单价+(weightend-weightstart)*续阶单价
			BigDecimal tmp= weightRecord.getPrice().multiply(totalChargeWeight.subtract(weightRecord.getWeightStart()).divide(weightRecord.getWeightCharging(),2,BigDecimal.ROUND_HALF_UP));
			for(int i=index-1 ;i>=0;i--){
				if(weightRecords.get(i).getChargingCode().equals("zj")){
					return tmp.add(weightRecords.get(i).getPrice());
				}else if (weightRecords.get(i).getChargingCode().equals("xjdj")){
					tmp=tmp.add(weightRecords.get(i).getPrice().multiply(weightRecord.getWeightEnd()
							.subtract(weightRecord.getWeightStart()).divide(weightRecord.getWeightCharging(),2,BigDecimal.ROUND_HALF_UP)));
				}else{
					throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
							TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
				}
			}
			return tmp;
		} else{
			throw new TmsManagerException(TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getCode(),
					TmsExceptionEnum.CHARGECODE_RULE_IS_ERROR.getMessage());
		}
	}

}
